package org.eiahe.hr.salary.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.vo.SysDeptVo;
import org.ehe.system.service.ISysDeptService;
import org.eiahe.hr.salary.domain.SalaryNotification;
import org.eiahe.hr.salary.domain.SalaryStructure;
import org.eiahe.hr.salary.domain.bo.SalaryNotificationBo;
import org.eiahe.hr.salary.domain.vo.SalaryNotificationVo;
import org.eiahe.hr.salary.mapper.SalaryNotificationMapper;
import org.eiahe.hr.salary.mapper.SalaryStructureMapper;
import org.eiahe.hr.salary.service.ISalaryNotificationService;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 薪资通知Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SalaryNotificationServiceImpl implements ISalaryNotificationService {

    private final SalaryNotificationMapper baseMapper;
    private final SalaryStructureMapper salaryStructureMapper;
    private final ISysDeptService deptService;

    @Override
    public SalaryNotificationVo queryById(Long notificationId) {
        SalaryNotificationVo salaryNotificationVo = baseMapper.selectVoById(notificationId);
        if(null != salaryNotificationVo.getDepartment()){
            SysDeptVo sysDeptVo = deptService.selectDeptById(salaryNotificationVo.getDepartment());
            if(Objects.nonNull(sysDeptVo)){
                salaryNotificationVo.setDepartmentName(sysDeptVo.getDeptName());
            }
        }
        return salaryNotificationVo;
    }

    @Override
    public List<SalaryNotificationVo> queryList(SalaryNotificationBo bo) {
        LambdaQueryWrapper<SalaryNotification> lqw = buildQueryWrapper(bo);
        List<SalaryNotificationVo> salaryNotificationVos = baseMapper.selectVoList(lqw);
        salaryNotificationVos.forEach(s->{
            if(null != s.getDepartment()){
                SysDeptVo sysDeptVo = deptService.selectDeptById(s.getDepartment());
                if(Objects.nonNull(sysDeptVo)){
                    s.setDepartmentName(sysDeptVo.getDeptName());
                }
            }
        });
        return salaryNotificationVos;
    }

    @Override
    public TableDataInfo<SalaryNotificationVo> queryPageList(SalaryNotificationBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SalaryNotification> lqw = buildQueryWrapper(bo);
        IPage<SalaryNotificationVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        page.getRecords().forEach(s->{
            if(null != s.getDepartment()){
                SysDeptVo sysDeptVo = deptService.selectDeptById(s.getDepartment());
                if(Objects.nonNull(sysDeptVo)){
                    s.setDepartmentName(sysDeptVo.getDeptName());
                }
            }
        });
        return TableDataInfo.build(page);
    }

    /**
     * 构建查询条件
     *
     * @param bo 薪资通知业务对象
     * @return 查询条件
     */
    private LambdaQueryWrapper<SalaryNotification> buildQueryWrapper(SalaryNotificationBo bo) {
        LambdaQueryWrapper<SalaryNotification> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), SalaryNotification::getEmployeeNo, bo.getEmployeeNo());
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeName()), SalaryNotification::getEmployeeName, bo.getEmployeeName());
        lqw.eq(StringUtils.isNotBlank(bo.getYearMonth()), SalaryNotification::getYearMonth, bo.getYearMonth());
        lqw.eq(StringUtils.isNotBlank(bo.getDepartment()), SalaryNotification::getDepartment, bo.getDepartment());
        lqw.eq(StringUtils.isNotBlank(bo.getNotificationStatus()), SalaryNotification::getNotificationStatus,
                bo.getNotificationStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SalaryNotification::getStatus, bo.getStatus());
        lqw.orderByDesc(SalaryNotification::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean insertByBo(SalaryNotificationBo bo) {
        SalaryNotification add = MapstructUtils.convert(bo, SalaryNotification.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setNotificationId(add.getNotificationId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(SalaryNotificationBo bo) {
        SalaryNotification update = MapstructUtils.convert(bo, SalaryNotification.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(SalaryNotification entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean generateNotifications(String yearMonth) {
        try {
            // 查询指定年月的所有薪资数据
            LambdaQueryWrapper<SalaryStructure> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(SalaryStructure::getYearMonth, yearMonth);
            queryWrapper.eq(SalaryStructure::getStatus, "0"); // 只查询正常状态的数据

            List<SalaryStructure> salaryList = salaryStructureMapper.selectList(queryWrapper);

            if (salaryList.isEmpty()) {
                return false;
            }

            // 为每个员工生成薪资通知
            for (SalaryStructure salary : salaryList) {
                // 检查是否已存在相同员工和年月的通知
                LambdaQueryWrapper<SalaryNotification> existQuery = Wrappers.lambdaQuery();
                existQuery.eq(SalaryNotification::getEmployeeNo, salary.getEmployeeNo());
                existQuery.eq(SalaryNotification::getYearMonth, yearMonth);

                SalaryNotification existing = baseMapper.selectOne(existQuery);

                if (existing == null) {
                    // 创建新的薪资通知
                    SalaryNotification notification = new SalaryNotification();
                    notification.setEmployeeNo(salary.getEmployeeNo());
                    notification.setEmployeeName(salary.getEmployeeName());
                    notification.setDepartment(salary.getDepartment());
                    notification.setYearMonth(yearMonth);
                    notification.setGrossSalary(salary.getGrossSalary());
                    notification.setNetSalary(salary.getNetSalary());
                    notification.setNotificationStatus("0"); // 未发送
                    notification.setStatus("0"); // 正常状态
                    baseMapper.insert(notification);
                }
            }

            return true;
        } catch (Exception e) {
            // 记录日志
            log.error("生成薪资通知失败", e);
            return false;
        }
    }

    @Override
    public Boolean sendNotification(Long notificationId) {
        try {
            SalaryNotification notification = baseMapper.selectById(notificationId);
            if (notification == null) {
                return false;
            }

            // 发送通知（集成多种通道）
            boolean sent = sendNotificationViaMultipleChannels(notification);

            if (sent) {
                // 更新通知状态为已发送
                notification.setNotificationStatus("1");
                notification.setSendTime(new Date());
                return baseMapper.updateById(notification) > 0;
            }

            return false;
        } catch (Exception e) {
            // 记录日志
            log.error("发送薪资通知失败", e);
            return false;
        }
    }

    /**
     * 通过多种通道发送通知
     *
     * @param notification 薪资通知
     * @return 是否发送成功
     */
    private boolean sendNotificationViaMultipleChannels(SalaryNotification notification) {
        try {
            // 构造通知内容
            String content = String.format("尊敬的%s，您的%s月份薪资已发放，实发工资为%.2f元。",
                    notification.getEmployeeName(),
                    notification.getYearMonth().substring(4),
                    notification.getNetSalary());

            // TODO: 这里应该根据员工的偏好设置选择发送通道
            // 目前默认发送邮件和短信

            // 发送邮件通知（需要配置邮件服务）
            boolean emailSent = sendEmailNotification(notification, content);

            // 发送短信通知（需要配置短信服务）
            boolean smsSent = sendSmsNotification(notification, content);

            // 发送企业微信通知（需要配置企业微信服务）
            boolean wechatSent = sendWechatNotification(notification, content);

            // 只要有一种方式发送成功就认为发送成功
            return emailSent || smsSent || wechatSent;
        } catch (Exception e) {
            // 记录日志
            log.error("发送通知失败", e);
            return false;
        }
    }

    /**
     * 发送邮件通知
     *
     * @param notification 薪资通知
     * @param content      通知内容
     * @return 是否发送成功
     */
    private boolean sendEmailNotification(SalaryNotification notification, String content) {
        try {
            // TODO: 需要获取员工的邮箱地址
            // 这里暂时使用示例邮箱
            String email = "employee@example.com";

            // 发送邮件（需要配置邮件服务）
            // MailUtils.sendText(email, "薪资发放通知", content);
            System.out.println("发送邮件通知到: " + email + ", 内容: " + content);
            return true;
        } catch (Exception e) {
            // 记录日志
            log.error("发送邮件通知失败", e);
            return false;
        }
    }

    /**
     * 发送短信通知
     *
     * @param notification 薪资通知
     * @param content      通知内容
     * @return 是否发送成功
     */
    private boolean sendSmsNotification(SalaryNotification notification, String content) {
        try {
            // TODO: 需要获取员工的手机号码
            // 这里暂时使用示例手机号
            String phoneNumber = "13800138000";

            // 发送短信（需要配置短信服务）
            // SmsUtils.sendSms(phoneNumber, content);
            System.out.println("发送短信通知到: " + phoneNumber + ", 内容: " + content);
            return true;
        } catch (Exception e) {
            // 记录日志
            log.error("发送短信通知失败", e);
            return false;
        }
    }

    /**
     * 发送企业微信通知
     *
     * @param notification 薪资通知
     * @param content      通知内容
     * @return 是否发送成功
     */
    private boolean sendWechatNotification(SalaryNotification notification, String content) {
        try {
            // TODO: 需要集成企业微信API
            // 这里暂时返回true表示发送成功
            System.out.println("发送企业微信通知: " + content);
            return true;
        } catch (Exception e) {
            // 记录日志
            log.error("发送企业微信通知失败", e);
            return false;
        }
    }

    @Override
    public Boolean markAsViewed(Long notificationId) {
        try {
            SalaryNotification notification = baseMapper.selectById(notificationId);
            if (notification == null) {
                return false;
            }

            // 更新通知状态为已查看
            notification.setNotificationStatus("2");
            notification.setViewTime(new Date());
            return baseMapper.updateById(notification) > 0;
        } catch (Exception e) {
            // 记录日志
            log.error("标记通知为已查看失败", e);
            return false;
        }
    }
}
